package JDBC.Dao;


import JDBC.bean.UserInfoBean;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author Zhang Chao
 * @Date 2021/6/9 16:55
 * @Version 1.0
 */
public class TestDriver {
    public static void main(String[] args) {
        // 原生jdbc连接数据库
//        testDataSource();
//        testDBUtils();
        testDBUtils2();
    }


    /**
     * 使用dbutils进行数据库操作
     * BeanListHandler
     */
    public static void testDBUtils2() {

        try {
            // 1 获取数据源对象 - dbcp数据源
            DataSource dataSource = DBCPDataSource.getDataSource();
            // 2 获取查询器 - dbutils使用 queryrunner作为数据库操作的查询器
            QueryRunner queryRunner = new QueryRunner(dataSource);
            // 3 准备sql语句
            String strSql = "SELECT * FROM userinfo";
            // 4 获取查询结果集
            List<UserInfoBean> lstRusultSet =
                    (List<UserInfoBean>) queryRunner.query(strSql, new BeanListHandler(UserInfoBean.class));
            // 5 遍历结果集，进行业务逻辑处理
            System.out.println("转储结果：");
            System.out.println(lstRusultSet);

            // Huoqu某一行数据
            System.out.println("第一行数据的用户名：");
            System.out.println(lstRusultSet.get(0).getUserName());

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 也可以在这里回收资源
        }
    }

    /**
     * java使用dbutuils进行查询操作
     */
    public static void testDBUtils() {

        try {
            // 1 获取数据源对象 - dbcp数据源
            DataSource dataSource = DBCPDataSource.getDataSource();
            // 2 获取查询器 - dbutils使用 queryrunner作为数据库操作的查询器
            QueryRunner queryRunner = new QueryRunner(dataSource);
            // 3 准备sql语句
            String strSql = "SELECT * FROM userinfo";
            // 4 获取查询结果集   （new MapListHandler()   类型标识接口  表示 使查询结果转化为：List<Map<String, Object>> ）
            List<Map<String, Object>> lstRusultSet = queryRunner.query(strSql, new MapListHandler());
            // 5 遍历结果集，进行业务逻辑处理
            System.out.println("转储结果：");
            System.out.println(lstRusultSet);

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 也可以在这里回收资源
        }
    }


    /**
     * java原生连接jdbc
     * 注意:
     * 1、java 的 jdbc连接的工具类都来自于 java.sql包，不要引错包
     * 2、数据库操作过程中的集合，比如resultset的下标是从1开始的
     */
    public static void testDataSource() {
        // 0 准备工作 在项目目录下新建一个lib目录，考入mysql驱动包，设置jar项目引用

        try {
            // 2 获取数据库连接对象
            Connection connection = DBCPDataSource.getDataSource().getConnection();
            // 3 获取查询器
            Statement statement = connection.createStatement();
            // 4 准备sql语句
            String strSql = "SELECT * FROM userinfo";
            // 5 获取查询结果集
            ResultSet resultSet = statement.executeQuery(strSql);
            // 6 遍历结果集，进行业务逻辑处理

            // TODO 查询完之后，需要将ResultSet中的结果数据，转储到一个集合数据结构中【List+Map】，
            //  然后关闭数据库资源，进行资源回收，减轻数据库服务器的压力； 写一个公用的方法完成这个业务处理；
            /*
              思路提示：
                 在resultset结果集中通过 ResultSetMetaData getMetaData()  方法可以获取，查询结果集中于列信息相关的数据，可以获取 列数；
                 可通过列数的下表获取列表，然可以通过列名从 resultset结果集中获取对应列的值，然后，以列明为key ，以列值为value，存入 map中；
                 然后map存入 list中，这样就完成了查询结果集 resultset的转储业务处理；
             */

            // 业务需要再一次遍历查询结果集的数据
            // 可以使用迭代的方式进行遍历
            // 因为resulstset结果集中使用的是 游标 进行查询结果的遍历 游标只能从前往后移动，到末尾结束
            // 如果再次遍历的话，需要将游标重置到开始位置
            resultSet.beforeFirst();
            System.out.println("将数据库中的数据转储到List+Map的结果集：");
            // 转储的数据结果集
            List<Map<String, Object>> lstRusultSet = new ArrayList<>();

            if (resultSet != null) {
                // 获取查询结果集列信息
                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                // 获取当前结果集中的列数
                int columnCount = resultSetMetaData.getColumnCount();
                while (resultSet.next()) {
                    // 保存当前行数据的Map对象，因为需要有序，所以使用 LinkedHashMap 实现类
                    Map<String, Object> map = new LinkedHashMap<>();

                    // 通过列数for循环获取每一列的名字，通过获取的列明，获取对应的列值
                    for (int i = 1; i <= columnCount; i++) {
                        // 获取对应下标的列名
                        String strColumnName = resultSetMetaData.getColumnName(i);
                        // 通过列名获取对应的列值
                        Object objColumnValue = resultSet.getObject(strColumnName);
                        // 把列名-列值 键值对存入map中
                        map.put(strColumnName, objColumnValue);
                    }

                    // 把保存每一行数据的map存入list中，一个map表示一行数据
                    lstRusultSet.add(map);

                    //使用getxxx方法获取指定名字或者下标的字段值
                    System.out.println(" 姓名：" + resultSet.getObject("userName") +
                            "; 电话：" + resultSet.getObject(5));
                }
            }

            // 测试转储结果
            System.out.println("转储结果：");
            System.out.println(lstRusultSet);

            // 回收资源
            resultSet.close();


            System.out.println("关闭查询器之后，再次遍历查询结果集中的数据【转储之后】：");
            System.out.println(lstRusultSet);

            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 也可以在这里回收资源
        }
    }

}
